package com.young.mylib;

import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.widget.Toast;

import com.young.mylib.utils.FileUtils;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.Thread.UncaughtExceptionHandler;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import static android.content.Context.ACTIVITY_SERVICE;

/**
 * <pre>
 *     author: young
 *     time  : 2016/9/27
 *     desc  : 崩溃相关工具类
 * </pre>
 */
public class CrashUtils
        implements UncaughtExceptionHandler {
    private final static String TAG = "CrashUtils";
    private volatile static CrashUtils mInstance;
    private static Context context;
    private UncaughtExceptionHandler mHandler;

    private boolean mInitialized;
    private String crashDir;
    private String versionName;
    private int versionCode;
    // 用于格式化日期,作为日志文件名的一部分
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

    public CrashUtils(Context context) {
        this.context = context;
    }


    /**
     * 初始化
     *
     * @return {@code true}: 成功<br>{@code false}: 失败
     */
    public boolean init() {
        if (mInitialized) return true;

        if (Environment.getExternalStorageState()
                .equals(Environment.MEDIA_MOUNTED)) {
            crashDir = FileUtils.getAppPath(context)+"crash/";

        } else {
            File baseCache = context.getCacheDir();
            if (baseCache == null) return false;
            crashDir = baseCache.getPath() + File.separator + "crash" + File.separator;

        }
        try {
            PackageInfo pi = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            versionName = pi.versionName;
            versionCode = pi.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return false;
        }
        mHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        Log.i(TAG, "crash init: " + crashDir);
        return mInitialized = true;
    }

    @Override
    public void uncaughtException(Thread thread, final Throwable throwable) {

        new Thread(new Runnable() {
            @Override
            public void run() {

                Writer writer = new StringWriter();
                PrintWriter pw = new PrintWriter(writer);

                pw.write(getCrashHead());
                throwable.printStackTrace(pw);

                Throwable cause = throwable.getCause();
                while (cause != null) {
                    cause.printStackTrace(pw);
                    cause = cause.getCause();
                }
                pw.flush();
                pw.close();
                try {
                    String now = new SimpleDateFormat("yy-MM-dd HH:mm:ss", Locale.getDefault()).format(new Date());
                    final String fullPath = crashDir + now + ".txt";
                    writeFile(fullPath,writer.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
        if (!handleException(throwable) && mHandler != null) {
            Log.i(TAG,"IF");
            mHandler.uncaughtException(thread, throwable);
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, "crash: " + e.getMessage());
            }
            exitApp();
        }else {
            Log.i(TAG,"ELSE");
//            try {
//                Thread.sleep(3000);
//            } catch (InterruptedException e) {
//                Log.e(TAG, "crash: " + e.getMessage());
//            }
            //退出程序
            exitApp();
        }

    }
private void exitApp(){
    int currentVersion = Build.VERSION.SDK_INT;
    if (currentVersion > Build.VERSION_CODES.ECLAIR_MR1) {
        Intent startMain = new Intent(Intent.ACTION_MAIN);
        startMain.addCategory(Intent.CATEGORY_HOME);
        startMain.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(startMain);
        System.exit(0);
    } else {// android2.1
        ActivityManager am = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
        am.restartPackage(context.getPackageName());
    }
}
    public static String writeFile(String fullPath,String sb) throws Exception {
        Log.e(TAG, sb);
        if (hasSdcard()) {
            Log.i(TAG, fullPath);
            if (!FileUtils.createOrExistsFile(fullPath)) return "connot create crash dir";
            FileOutputStream fos = new FileOutputStream(fullPath, true);
            fos.write(sb.getBytes());
            fos.flush();
            fos.close();
            return fullPath;
        }
        return "hasn`t sdcard";
    }

    public static boolean hasSdcard() {
        String status = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(status);
    }

    private boolean handleException(final Throwable ex) {
        if (ex == null) {
            Log.e(TAG,"EX IS NULL");
            return false;
        }
        try {
            // 使用Toast来显示异常信息
            new Thread() {

                @Override
                public void run() {
                    Looper.prepare();
                    Toast.makeText(context, "Sorry,Some mistakes happened!",
                            Toast.LENGTH_LONG).show();
                    if (ex != null && ex.getMessage() != null) {
                        Log.e(TAG, ex.getMessage());
                    } else {
                        Log.e(TAG, "程序出现异常 ex is null");
                    }
                    Looper.loop();
                }
            }.start();
            // 收集设备参数信息

            SystemClock.sleep(3000);
        } catch (Exception e) {
            Log.e(TAG,"handleException: "+e.getMessage());
            e.printStackTrace();
        }
        Log.e(TAG,"handleException: return true");
        return true;
    }

    /**
     * 获取崩溃头
     *
     * @return 崩溃头
     */
    private String getCrashHead() {
        return "\n************* Crash Log Head ****************" +
                "\nDevice Manufacturer: " + Build.MANUFACTURER +// 设备厂商
                "\nDevice Model       : " + Build.MODEL +// 设备型号
                "\nAndroid Version    : " + Build.VERSION.RELEASE +// 系统版本
                "\nAndroid SDK        : " + Build.VERSION.SDK_INT +// SDK版本
                "\nApp VersionName    : " + versionName +
                "\nApp VersionCode    : " + versionCode +
                "\n************* Crash Log Head ****************\n\n";
    }

    /**
     * 关闭IO
     *
     * @param closeables closeable
     */
    public static void closeIO(Closeable... closeables) {
        if (closeables == null) return;
        for (Closeable closeable : closeables) {
            if (closeable != null) {
                try {
                    closeable.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
